﻿using System.IO;
using System.Linq;
using CID.Execution.Agent.PackageHandling;
using CID.Execution.Support.Information;
using CID.Execution.Support.PackageHandling;
using NUnit.Framework;

namespace CID.Execution.Agent.Tests.PackageHandling
{
    [TestFixture]
    class ZIPPackageHandlerTests : BaseAgentTests
    {
        private static readonly string[] ValidPackageStructure = new string[] {
            "ComplexDirectory", "SimpleDirectory", "MainPackageFile.txt",
            @"ComplexDirectory\FirstSubdirectory", @"ComplexDirectory\SecondSubdirectory", @"ComplexDirectory\File1.txt", @"ComplexDirectory\File2.txt",
            @"ComplexDirectory\FirstSubdirectory\SubSubdirectory", @"ComplexDirectory\FirstSubdirectory\File1.txt", @"ComplexDirectory\FirstSubdirectory\File2.txt",
            @"ComplexDirectory\FirstSubdirectory\SubSubdirectory\File1.txt",@"ComplexDirectory\FirstSubdirectory\SubSubdirectory\File2.txt",
            @"ComplexDirectory\SecondSubdirectory\File1.txt", @"ComplexDirectory\SecondSubdirectory\File2.txt",
            @"SimpleDirectory\File1.txt", @"SimpleDirectory\File2.txt"
        };
        private const string ValidPackageFileContent = "File Content 123";

        private const string ValidPackagePath = @".\Artifacts\ValidPackage.zip";
        private const string InvalidPackagePath = @".\Artifacts\InvalidPackage.zip";
        
        ZIPPackageHandler packageHandler;
        ZIPPackageHandlingToken token;
        PackageInfo packageInfo;

        public override void SetUp()
        {
            base.SetUp();

            packageHandler = new ZIPPackageHandler();
            packageInfo = new PackageInfo();
            packageInfo.Comment = "Some Comment";
            packageInfo.Content = File.ReadAllBytes(ValidPackagePath);
        }

        public override void TearDown()
        {
            base.TearDown();

            if (token != null) packageHandler.Release(token);
        }

        #region PrepareForUsage
        [Test]
        public void PrepareForUsage_ValidPackage_ShouldExtractPackage()
        {
            token = packageHandler.PrepareForUsage(packageInfo) as ZIPPackageHandlingToken;

            var entries = Directory.GetFileSystemEntries(token.TargetDirectoryPath, "*", SearchOption.AllDirectories)
                .Select(x => x.Remove(0, token.TargetDirectoryPath.Length + 1)).ToArray();
            var files = Directory.GetFiles(token.TargetDirectoryPath, "*", SearchOption.AllDirectories);

            Assert.IsTrue(Directory.Exists(token.TempPath));
            Assert.IsTrue(Directory.Exists(token.TargetDirectoryPath));
            CollectionAssert.AreEquivalent(ValidPackageStructure, entries);
            foreach (var file in files)
                Assert.AreEqual(ValidPackageFileContent, File.ReadAllText(file));
        }

        [Test, ExpectedException(typeof(PackageHandlingException))]
        public void PrepareForUsage_InvalidPackage_ShouldThrowException()
        {
            packageInfo.Content = File.ReadAllBytes(InvalidPackagePath);

            packageHandler.PrepareForUsage(packageInfo);
        }
        #endregion

        #region Release
        [Test]
        public void Release_ValidPackageExctracted_ShouldRemoveEverything()
        {
            token = packageHandler.PrepareForUsage(packageInfo) as ZIPPackageHandlingToken;

            packageHandler.Release(token);

            Assert.IsFalse(Directory.Exists(token.TempPath));
            Assert.IsFalse(Directory.Exists(token.TargetDirectoryPath));
            token = null;
        }
        #endregion
    }
}
